package main

import (
	"context"
	"errors"
	"fmt"
	"github.com/redis/go-redis/v9"
	"time"
)

var ctx = context.Background()

// https://github.com/redis/go-redis
// 看上面的介绍，包括分布式锁、限速、订阅、管道&事务、集群、哨兵等都可以找到
func main() {
	//go-redis 既支持ip:port方式，也支持redis-url
	rdb := redis.NewClient(&redis.Options{
		Addr:     "127.0.0.1:6379",
		Password: "",
		DB:       0,
		Protocol: 3, // specify 2 for RESP 2 or 3 for RESP 3
	})
	/*
		url := "redis://user:password@localhost:6379/0?protocol=3"
		    opts, err := redis.ParseURL(url)
		    if err != nil {
		        panic(err)
		    }
		rdb := redis.NewClient(opts)
	*/

	//*表示获取所有的key
	keys, err := rdb.Keys(ctx, "*").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println("keys(*):", keys)

	//
	err = rdb.Set(ctx, "key", "value", 0).Err()
	if err != nil {
		panic(err)
	}

	//
	val, err := rdb.Get(ctx, "key").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println("key:", val)

	//
	val2, err := rdb.Get(ctx, "key2").Result()
	if errors.Is(err, redis.Nil) {
		fmt.Println("key2 does not exist")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("key2", val2)
	}
	// Output: key value
	// key2 does not exist

	fmt.Println("------------------")
	test(rdb)
}
func test(rdb *redis.Client) {
	{ // SET key value EX 10 NX
		//已存在 返回false，否则返回true
		done, err := rdb.SetNX(ctx, "key", "value", 10*time.Second).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("setNx key:", done)
		fmt.Println("------------------")
	}
	{ // SET key value EX 10 NX
		//已存在 返回false，否则返回true
		done, err := rdb.SetNX(ctx, "x", "value", 10*time.Second).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("setNx x:", done)
		fmt.Println("------------------")
	}

	{ // SET key value keepttl NX
		//已存在 返回false，否则返回true
		done, err := rdb.SetNX(ctx, "key", "value", redis.KeepTTL).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("setNx keepTtl key:", done)
		fmt.Println("------------------")
	}
	{ // SET key value keepttl NX
		//已存在 返回false，否则返回true
		done, err := rdb.SetNX(ctx, "y", "value", redis.KeepTTL).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("setNx keepTtl y:", done)
		fmt.Println("------------------")
	}

	{ // SORT list LIMIT 0 2 ASC
		vals, err := rdb.Sort(ctx, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("Sort:", vals)
		fmt.Println("------------------")
	}
	{ // ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2
		vals, err := rdb.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{
			Min:    "-inf",
			Max:    "+inf",
			Offset: 0,
			Count:  2,
		}).Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("ZRangeByScoreWithScores:", vals)
		fmt.Println("------------------")
	}
	{ // ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM
		vals, err := rdb.ZInterStore(ctx, "out", &redis.ZStore{
			Keys:    []string{"zset1", "zset2"},
			Weights: []float64{2, 3},
		}).Result()

		if err != nil {
			panic(err)
		}
		fmt.Println("ZInterStore:", vals)
		fmt.Println("------------------")
	}

	{ // EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello"
		vals, err := rdb.Eval(ctx, "return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("Eval:", vals)
		fmt.Println("------------------")
	}

	{ // custom command
		res, err := rdb.Do(ctx, "set", "key", "value").Result()
		if err != nil {
			panic(err)
		}
		fmt.Println("Do:", res)
		fmt.Println("------------------")
	}
}
